package com.sensetime.bi.senselink.server.rtsp.server;

import com.sensetime.bi.senselink.server.handler.ForwardRTPToMediaHandler;
import com.sensetime.bi.senselink.server.handler.ForwardRTPToPlayerHandler;
import com.sensetime.bi.senselink.server.handler.RtspRequestHandler;
import com.sensetime.bi.senselink.server.parse.PackageDecoder;
import com.sensetime.bi.senselink.server.parse.RtpEncoder;
import com.sensetime.bi.senselink.server.rtsp.server.processor.IRtspRequest;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.CharsetUtil;
import io.netty.util.ResourceLeakDetector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * @author liugaowei
 * @description RTSP server
 */
@Slf4j
@Component
public class RtspServer implements Runnable{

    @Value("${rtsp.server.port}")
    private int serverPort;

    @Autowired
//    @Qualifier("RtspFileRequestProcessor")
    @Qualifier("RtspProxyProcessor")
    private IRtspRequest rtspProcessor;
//
//    @Autowired
//    private RtspServerInitializer rtspServerInitializer;

    public void run(){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel> () {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();
                            pipeline.addLast("RawPackagedecoder", new PackageDecoder());
                            pipeline.addLast("handler", new RtspRequestHandler(rtspProcessor));
                            pipeline.addLast("rtspEncoder", new StringEncoder(CharsetUtil.UTF_8));
                            pipeline.addLast("ForwardRTPToMediaHandler", new ForwardRTPToMediaHandler());
                            pipeline.addLast("rtpEncoder", new RtpEncoder());
                        }
                    })
//                    .childHandler(rtspServerInitializer)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(131070));
            // 检测内存泄露
            ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);

            ChannelFuture rtspServerFuture = b.bind(serverPort).sync();
            log.info("rtsp server listening at " + serverPort);
            //不阻塞。
            rtspServerFuture.channel().closeFuture().addListener((ChannelFutureListener) future -> {
                //通过回调只关闭自己监听的channel
                future.channel().close();
            });
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}
